<?php

//
// Stone大叔💯 
// ============================================================================
// ----------------------------------------------------------------------------
// <><><><><><><><><><><><><>有妹子加微信不哦！~<><><><><><><><><><><><><><><><>
// ----------------------------------------------------------------------------
// ============================================================================
// $Author: Stone大叔💯 $
// $Z Stone大叔💯 $
//

namespace Stone\Core;

class App{   
    
    static private $_instance = NULL;
    
    static private $_map    =   NULL;
    
    // 建立唯一进程, 有且只有一个, 为了不影响程序运行, 不重新实例化.
    static function _get_instance() {
            self::$_instance === NULL && self::$_instance = new App();
    }
    
    public function __construct() {  
        // 注册AUTOLOAD方法
        spl_autoload_register('Stone\Core\App::autoload'); 
        // 设定错误和异常处理
        register_shutdown_function('Stone\Core\App::fatalError');
        set_error_handler('Stone\Core\App::appError');
        set_exception_handler('Stone\Core\App::appException'); 
        
    }
    
    /**
     * 自动加载
     * @param type $param
     */
    static public function autoload($class) {
        //smarty
        
        // 检查是否存在映射
        if(isset(self::$_map[$class])) {           
        }else if(false !== strpos($class,'\\')){       
           $filename       =   $class . EXT;
           
            if(is_file( dirname(ROOT_PATH). DIRECTORY_SEPARATOR . $filename )){                
                $filename   =   dirname(ROOT_PATH). DIRECTORY_SEPARATOR . $filename;
            }elseif(is_file( dirname(FRAMEWORK_PATH). DIRECTORY_SEPARATOR . $filename )){
                $filename   =   dirname(FRAMEWORK_PATH). DIRECTORY_SEPARATOR . $filename;
            }elseif(defined('APP_PATH') && is_file(dirname(APP_PATH). DIRECTORY_SEPARATOR . $filename )){
                $filename   =   dirname(APP_PATH) . DIRECTORY_SEPARATOR . $filename;
            }
            
            if(is_file($filename)) {
                self::$_map[$class] =   $filename;
                include $filename;
            }
            
        }else{
            $filename   =   $class . EXT;
            if(is_file($filename)) {
                self::$_map[$class] =   $filename;
                include $filename;
            }            
        }
       
    } 

    
    /**
     * 自定义异常处理
     * @access public
     * @param mixed $e 异常对象
     */
    static public function appException($e) {
        $error = array();
        $error['message']   =   $e->getMessage();
        $trace              =   $e->getTrace();
        if('E'==$trace[0]['function']) {
            $error['file']  =   $trace[0]['file'];
            $error['line']  =   $trace[0]['line'];
        }else{
            $error['file']  =   $e->getFile();
            $error['line']  =   $e->getLine();
        }
        $error['trace']     =   $e->getTraceAsString();
        
        \Stone\Core\Log::write($error['message']);
        
        // 发送404信息
        header('HTTP/1.1 404 Not Found');
        header('Status:404 Not Found');
        self::halt($error);
    }

    /**
     * 自定义错误处理
     * @access public
     * @param int $errno 错误类型
     * @param string $errstr 错误信息
     * @param string $errfile 错误文件
     * @param int $errline 错误行数
     * @return void
     */
    static public function appError($errno, $errstr, $errfile, $errline) {
      switch ($errno) {
          case E_ERROR:
          case E_PARSE:
          case E_CORE_ERROR:
          case E_COMPILE_ERROR:
          case E_USER_ERROR:
            ob_end_clean();
            $errorStr = "$errstr ".$errfile." 第 $errline 行.";
            \Stone\Core\Log::write("[$errno] ".$errorStr);
            self::halt($errorStr);
            break;
          default:
            $errorStr = "[$errno] $errstr ".$errfile." 第 $errline 行.";
            \Stone\Core\Log::write("[$errno] ".$errorStr);
            self::halt($errorStr);
            break;
      }
    }
    
    // 致命错误捕获
    static public function fatalError() {
        if ($e = error_get_last()) {
            switch($e['type']){
              case E_ERROR:
              case E_PARSE:
              case E_CORE_ERROR:
              case E_COMPILE_ERROR:
              case E_USER_ERROR:  
                ob_end_clean();
                self::halt($e);
                break;
            }
        }
    }
    /**
     * 错误输出
     * @param mixed $error 错误
     * @return void
     */
    static public function halt($error) {
        $e = array();
        if (!is_array($error)) {
            $trace          = debug_backtrace();
            $e['message']   = $error;
            $e['file']      = $trace[0]['file'];
            $e['line']      = $trace[0]['line'];
            ob_start();
            debug_print_backtrace();
            $e['trace']     = ob_get_clean();
        } else {
            $e              = $error;
        }       
     
        // 包含异常页面模板
        $exceptionFile  =   ROOT_PATH . TPL_PATH . "exception.tpl"; 
        if(!file_exists($exceptionFile)){
            $exceptionFile  =   FRAMEWORK_PATH . TPL_PATH . "exception.tpl"; 
        }        
        include $exceptionFile;
        
        exit;
    }
    
    
    
    protected function __clone() {}
    
}
